﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WevPanel
{
    public class WaveGrapher
    {
        private ZedGraph.ZedGraphControl z_;
        private ZedGraph.GraphPane pane_;
        public AdChannel[] channels;
        public int channel_length;          // 启用的通道数
        public Queue<double> axis_x;
        DateTime start_time;

        public WaveGrapher(ref ZedGraph.ZedGraphControl z)
        {
            z_ = z;
            start_time = DateTime.Now;
            pane_ = z_.GraphPane;
            pane_.IsFontsScaled = false; //禁用自动调整字体大小
            pane_.Title.FontSpec.Size = 12.0F; //设置标题字体
            pane_.Title.Text = "Driver Curves";
            pane_.XAxis.Title.Text = "Time(s)";
            channels = new AdChannel[4];
            axis_x = new Queue<double>(); 
            for (int i = 0; i < channels.Length; i++)
            {
                channels[i] = new AdChannel(i);
                channels[i].lineColor = AdChannel.lineColors[i];
            }
        }

        public void InitAxis(string[] name_list)
        {
            pane_.YAxisList.Clear();
            start_time = DateTime.Now;
            axis_x.Clear();
            if (name_list.Length > 4)
                return;
            channel_length = name_list.Length;
            for(int i=0;i<name_list.Length;i++)
            {
                channels[i].buffer.Clear();
                channels[i].valueName = name_list[i];
                pane_.AddYAxis(name_list[i]);
                pane_.YAxisList[i].Title.Text = name_list[i];
            }
            pane_.AxisChange();
            z_.Refresh();
        }

        public void ShowCurve(string legend, double[] x, double[] y, string x_title = "x-series", string y_title = "y-series")
        {
            pane_.CurveList.Clear();
            var curve_ct = pane_.AddCurve(legend, x, y, Color.Black, ZedGraph.SymbolType.Circle);
            curve_ct.Line.Width = 2;
            curve_ct.Symbol.Border.Color = Color.Red;
            curve_ct.Symbol.Border.Width = 2;
            curve_ct.Symbol.Fill.IsVisible = true;
            curve_ct.Symbol.Fill.Brush = new SolidBrush(Color.Red);
            pane_.XAxis.Title.Text = x_title;
            pane_.YAxis.Title.Text = y_title;
            pane_.AxisChange();
            z_.Refresh();
        }

        public void RefreshCurve()
        {
            pane_.CurveList.Clear();
            double[] x = axis_x.ToArray();
            for(int i=0;i<channel_length;i++)
            {
                ZedGraph.LineItem curve_ct;
                AdChannel ch = channels[i];
                curve_ct = pane_.AddCurve(ch.valueName, x, ch.buffer.ToArray(), ch.lineColor, ZedGraph.SymbolType.None);
                curve_ct.YAxisIndex = i;
                curve_ct.Line.Width = ch.lineWidth;
            }
            pane_.XAxis.Scale.Min = x[0];
            pane_.XAxis.Scale.Max = x[x.Length - 1];
            pane_.AxisChange();
            z_.Refresh();
        }

        public void AddPoints(double[] points)
        {
            if (points.Length > channel_length)
                return;
            axis_x.Enqueue((DateTime.Now-start_time).TotalMilliseconds);
            if (axis_x.Count > channels[0].curveLength)
                axis_x.Dequeue();
            for(int i=0;i<points.Length;i++)
            {
                channels[i].AddPoint(points[i]);
            }
        }
    }

    public class AdChannel
    {
        public static Color[] lineColors = new[] { Color.Red, Color.Black, Color.Blue, Color.Green, Color.Yellow, Color.Purple, Color.Pink, Color.SaddleBrown }; // 默认的曲线颜色
        public Queue<double> buffer;

        [Description("曲线长度")]
        public int curveLength { get; set; }

        [Description("曲线变量名")]
        public string valueName { get; set; }

        [Description("曲线的颜色")]
        public Color lineColor { get; set; }

        [Description("曲线粗细")]
        public int lineWidth { get; set; }

        [Description("最大值")]
        public double max { get; set; }

        [Description("最小值")]
        public double min { get; set; }

        [Description("通道编号")]
        public int index { get; set; }

        public void AddPoint(double value)
        {
            buffer.Enqueue(value);
            if (buffer.Count > curveLength)
                buffer.Dequeue();
        }

        public AdChannel(int i)
        {
            lineWidth = 2;
            index = i;
            curveLength = 500;
            buffer = new Queue<double>();
        }

    }
}
